package com.MSofLectures.logistic;

import java.util.Iterator;
import java.util.List;

import com.MSofLectures.DatabaseBasic;
import com.MSofLectures.DAO.User_registerLecture;
import com.MSofLectures.Operator.Lecture.OperatorOnLecture;
import com.MSofLectures.Operator.Lecture.OperatorOnLectureImp;
import com.MSofLectures.Tool.Comparer;
import com.MSofLectures.Tool.DatabaseControler;
import com.MSofLectures.Tool.Sorter;

public class ShakerOfUsers {
	/*
	 * @author ufo
	 * 摇号器
	 */
	private DatabaseControler databaseControler = new DatabaseControler(DatabaseBasic.getSf());

	protected OperatorOnLectureImp operatorOnLecture=null;

	public void shake(String lectureId) {
		List<String> studentsRegistedLecture = getStudentsRegistedLecture(lectureId);
		Iterator<String> studentId = studentsRegistedLecture.iterator();

		Integer[][] studentScore = new Integer[studentsRegistedLecture.size()][2];// 优先级分数数组，分数高的优先级高
		Integer tmp = 0;
		for (; studentId.hasNext(); tmp++) {
			String tmpId = studentId.next();
			
			studentScore[tmp][0] = 1 * getTimes(tmpId, lectureId, false)// 报名但是没有被选中
					- 100 * getTimes(tmpId, lectureId, true);// 报名且被选中
			studentScore[tmp][1] = Integer.parseInt(tmpId);
		}
		Sorter.quickSort(studentScore, new Comparer() {

			@Override
			public boolean compare(Object a, Object b) {
				// TODO 自动生成的方法存根
				return ((Integer[]) a)[0] <= ((Integer[]) b)[0];
			}
		});
		register(shake(studentScore, lectureId),lectureId);
	}

	private void register(Integer[] studentId,String lectureId) {
		for (Integer i = 0; i < studentId.length; i++) {
			List<?> list = this.databaseControler.hibernateSess
					.createQuery(
							"from User_registerLecture where userId= :userId and lectureId=:lectureId")
					.setString("userId", studentId[i].toString())
					.setString("lectureId", lectureId)
					.list();
			Iterator<?> tmp = list.iterator();
			User_registerLecture lecture = (User_registerLecture) tmp.next();
			lecture.setUser_registerLecture_checked((byte) 1);
			lecture.setUser_registerLecture_checkedOrder(i.toString());
			this.databaseControler.save(lecture);
		}
		this.databaseControler.commit();
	}

	private String getLecture_keyNameId(String lecture_keyName) {
		List<?> list = this.databaseControler.hibernateSess
				.createQuery(
						"select lecture_keyNameId from Lecture_keyName where lecture_keyName=:lecture_keyName")
				.setString("lecture_keyName", lecture_keyName).list();
		Iterator<?> i = list.iterator();
		if (i.hasNext())
			return i.next().toString();
		else
			return null;
	}

	private List<String> getStudentsRegistedLecture(String lectureId) {
		List list = this.databaseControler.hibernateSess
				.createQuery(
						"select userId from User_registerLecture where "
								+ "lectureId=:lectureId")
				.setString("lectureId", lectureId).list();
		return list;
	}

	private Integer getTimes(String userId, String lectureId,
			boolean user_registerLecture_checked) {
		com.MSofLectures.Entity.Lecture.LectureImp lecture = this.getOperatorOnLecture()
				.loadLecture(lectureId);
		List<?> list = this.databaseControler.hibernateSess
				.createQuery(
						"from User_registerLecture where userId=:userId and user_registerLecture_checked=:user_registerLecture_checked")
				.setString("userId", userId)
				.setByte("user_registerLecture_checked",
						(byte) (user_registerLecture_checked ? 1 : 0)).list();
		Iterator<?> i = list.iterator();
		int result = 0;
		while (i.hasNext()) {
			com.MSofLectures.DAO.User_registerLecture register = (User_registerLecture) i
					.next();
			com.MSofLectures.Entity.Lecture.LectureImp lectureTmp = this.getOperatorOnLecture()
					.loadLecture(register.getLectureId());
			if (lecture.getValue("lecYear").equals(
					lectureTmp.getValue("lecYear"))
					&& lectureTmp.getValue("shake").equals("1"))
				result++;
		}
		;
		return result;
	}

	private Integer[] shake(Integer[][] studentScore, String lectureId) {
		Integer max = Integer
				.parseInt(this.databaseControler.hibernateSess
						.createQuery(
								"select lecture_keyValue from Lecture_keyValue where lectureId=:lectureId and lecture_keyNameId=:lecture_keyNameId")
						.setString("lectureId", lectureId)
						.setString("lecture_keyNameId",
								getLecture_keyNameId("lecCodeNumber")).list()
						.iterator().next().toString());
		// 摇号，分组抽选
		Integer min = max - 1 > studentScore.length - 1 ? studentScore.length - 1
				: max - 1;
		Integer start = min;
		Integer end = min;
		
		boolean flag = true;
		while (flag)
			// 要考虑报名人数少于总人数
			if (end < studentScore.length)
				if (studentScore[end] == studentScore[min])
					end++;
				else
					flag = false;
			else
				flag = false;
		end--;
		flag = true;
		while (flag)
			if (start >= 0)
				if (studentScore[start] == studentScore[min])
					start--;
				else
					flag = false;
			else
				flag = false;
		start++;
		// 到此为止，应当有studentScore[start] == studentScore[min]==studentScore[end]
		// 下面要把所有start到end的进行挑选，包括start和end
		Integer[] target = new Integer[min + 1];
		if(max-1==min)//票比人少
			if (end != start) {
				Integer amount = min - start + 1;//要抽出来的人数，同时也应该是分组的数量
				Integer zoom = (end - start + 1) / amount ;//每组人数
	//			zoom = (0 == zoom) ? 1 : zoom;
				Integer step = (int) (Math.random() * zoom);//每组抽选的那个人的序号
				step = (step == zoom) ? step - 1 : step;
				for (int i = start, j = start; i <= end; j++, i += zoom) {
					// 类似于分组抽样……
					target[j] = studentScore[i + step][1];
				}
			}else//人比票少
				start=min;
		for (Integer tmp1 = 0; tmp1 <=start; tmp1++){
			target[tmp1] = studentScore[tmp1][1];
		}
		return target;
	}
	public void finalize() throws Throwable{//为garbage collection准备，无需关注
		System.out.println("ShakerOfUsers collect");
		this.databaseControler.finalize();
		super.finalize();
	}

	public OperatorOnLectureImp getOperatorOnLecture() {
		if(null==this.operatorOnLecture)
			this.operatorOnLecture=new OperatorOnLecture();
		return this.operatorOnLecture;
	}

	public void setOperatorOnLecture(OperatorOnLectureImp operatorOnLecture) {
		this.operatorOnLecture = operatorOnLecture;
	}
}
